home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / mus / play / tracker_4_31.lzh / tracker / Unix / ui.c
C/C++ Source or Header  |  1995-05-15  |  10KB  |  552 lines

  1. /* unix/ui.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4.  
  5. /* Set terminal discipline to non blocking io and such.
  6.  */
  7. /* $Id: ui.c,v 4.16 1995/05/15 12:20:16 espie Exp espie $
  8.  * $Log: ui.c,v $
  9.  * Revision 4.16  1995/05/15  12:20:16  espie
  10.  * *** empty log message ***
  11.  *
  12.  * Revision 4.15  1995/05/12  20:41:31  espie
  13.  * Added audio_ui call.
  14.  *
  15.  * Revision 4.14  1995/05/12  13:53:47  espie
  16.  * New synchronization.
  17.  *
  18.  * Revision 4.13  1995/05/11  12:05:05  espie
  19.  * Old code trimmed away.
  20.  *
  21.  * Revision 4.12  1995/03/17  00:32:53  espie
  22.  * PREF XTERM code.
  23.  *
  24.  * Revision 4.11  1995/03/11  23:06:51  espie
  25.  * Display everything in titlebars for xterms.
  26.  *
  27.  * Revision 4.10  1995/03/06  23:36:30  espie
  28.  * Proper color patch.
  29.  *
  30.  * Revision 4.9  1995/03/03  14:24:40  espie
  31.  * Color fixed.
  32.  *
  33.  * Revision 4.8  1995/02/27  14:26:34  espie
  34.  * Cleaned up by Rolf Grossmann.
  35.  *
  36.  * Revision 4.7  1995/02/26  23:08:55  espie
  37.  * POSIX_CONFORMANT.
  38.  *
  39.  * Revision 4.6  1995/02/24  15:40:38  espie
  40.  * Removed all dependencies from show (cached PREF_SHOW) and
  41.  * fixed a small display bug therefore.
  42.  *
  43.  * Revision 4.5  1995/02/21  17:59:26  espie
  44.  * Internal problem: bad log with rcs.
  45.  *
  46.  * Revision 4.4  1995/02/08  13:47:35  espie
  47.  * *** empty log message ***
  48.  *
  49.  * Revision 4.3  1995/01/28  09:56:53  espie
  50.  * Port to FreeBSD/NeXTstep.
  51.  *
  52.  * Revision 4.2  1995/01/28  09:23:38  espie
  53.  * Support for old bsd io discipline (NeXT)
  54.  *
  55.  *
  56.  * Revision 4.0  1994/01/11  18:02:31  espie
  57.  * Major change: lots of new calls.
  58.  * Stupid termio bug: shouldn't restore term to sanity if we don't
  59.  * know what sanity is. For instance, if we haven't modified anything.
  60.  * cflags interpreted correctly.
  61.  * Hsavolai fix.
  62.  * Added bg/fg test.
  63.  */
  64.  
  65.  
  66. #include <sys/ioctl.h>
  67. #include <signal.h>
  68.  
  69. #include "defs.h"
  70. #include "extern.h"
  71. #include "tags.h"
  72. #include "prefs.h"
  73.  
  74. extern char *VERSION;
  75.  
  76. #ifdef USE_TERMIOS
  77. #include <sys/termios.h>    /* this should work on all posix hosts */
  78. #endif
  79. #ifdef USE_SGTTY                /* only NeXt does, currently */
  80. #include <sgtty.h>
  81. #include <fcntl.h>
  82. #endif
  83.  
  84. #ifdef __hpux
  85. #include <sys/bsdtty.h>
  86. #endif
  87.  
  88. LOCAL void nonblocking_io P((void));
  89. LOCAL void sane_tty P((void));
  90.  
  91. LOCAL void (*INIT)P((void)) = nonblocking_io;
  92.  
  93.  
  94. /* poor man's timer */
  95. LOCAL int current_pattern;
  96. LOCAL int count_pattern, count_song;
  97. #define SMALL_DELAY 75
  98.  
  99. /* do not define any stdio routines if it's known not to work */
  100.  
  101. #ifdef stub_only
  102.  
  103. int run_in_fg()
  104.    {
  105.    return TRUE;
  106.    }
  107.  
  108. LOCAL void sane_tty()
  109.    {
  110.    }
  111.  
  112. LOCAL struct tag end_marker;
  113.  
  114. struct tag *get_ui()
  115.    {
  116.    end_marker.type = TAG_END;
  117.    return &end_marker;
  118.    }
  119.  
  120. #else
  121.  
  122. #ifdef USE_SGTTY
  123. LOCAL struct sgttyb sanity;
  124. LOCAL struct sgttyb *psanity = 0;
  125. #endif
  126. #ifdef USE_TERMIOS
  127. LOCAL struct termios sanity;
  128. LOCAL struct termios *psanity = 0;
  129. #endif
  130.  
  131. LOCAL int is_fg;
  132.  
  133. /* signal handler */
  134.  
  135. LOCAL void goodbye(sig)
  136. int sig;
  137.    {
  138.    static char buffer[25];
  139.     char *pter = buffer;
  140.  
  141.     if (get_pref_scalar(PREF_COLOR))
  142.         pter = write_color(pter, 0);
  143.     sprintf(pter, "Signal %d", sig);
  144.    end_all(pter);
  145.    }
  146.  
  147. LOCAL void abort_this(sig)
  148. int sig;
  149.    {
  150.    end_all("Abort");
  151.    }
  152.  
  153. #ifdef SIGTSTP
  154. LOCAL void suspend(sig)
  155. int sig;
  156.    {
  157.     static char buffer[25];
  158.     char *buf = buffer;
  159.     
  160.     if (get_pref_scalar(PREF_COLOR))
  161.         buf = write_color(buf, 0);
  162.     *buf = 0;
  163.     puts(buf);
  164.    fflush(stdout);
  165.    sane_tty();
  166.    signal(SIGTSTP, SIG_DFL);
  167.    kill(0, SIGTSTP);
  168.    }
  169. #endif
  170.  
  171. int run_in_fg()
  172.    {
  173.    int val;
  174.  
  175.         /* this should work on every unix */
  176.     if (!isatty(fileno(stdin)) || !isatty(fileno(stdout)))
  177.         return FALSE;
  178.  
  179.    /* real check for running in foreground */
  180.    if (ioctl(fileno(stdin), TIOCGPGRP, &val))
  181.       return FALSE;
  182. #ifdef IS_POSIX
  183.    if (val == getpgrp())
  184. #else
  185.    if (val == getpgrp(0))
  186. #endif
  187.       return TRUE;
  188.    else
  189.       return FALSE;
  190.    }
  191.  
  192. /* if_fg_sane_tty():
  193.  * restore tty modes, _only_ if running in foreground
  194.  */
  195. LOCAL void if_fg_sane_tty()
  196.     {
  197.     if (run_in_fg())
  198.         sane_tty();
  199.     }
  200.  
  201.  
  202. LOCAL void switch_mode()
  203.    {
  204. #ifdef USE_SGTTY
  205.    struct sgttyb zap;
  206.    int tty;
  207. #endif
  208. #ifdef USE_TERMIOS
  209.    struct termios zap;
  210. #endif
  211.  
  212. #ifdef SIGTSTP
  213.    signal(SIGTSTP, suspend);
  214. #endif
  215.    signal(SIGCONT, switch_mode);
  216.    signal(SIGINT, goodbye);
  217.    signal(SIGQUIT, goodbye);
  218.    signal(SIGUSR1, abort_this);
  219.  
  220.    if (run_in_fg())
  221.       {
  222. #ifdef USE_SGTTY
  223.       tty = fileno(stdin);
  224.       fcntl(tty, F_SETFL, fcntl(tty, F_GETFL, 0) | FNDELAY);
  225.       ioctl(tty, TIOCGETP, &zap);
  226.       zap.sg_flags |= CBREAK;
  227.       zap.sg_flags &= ~ECHO;
  228.       ioctl(tty, TIOCSETP, &zap);
  229. #endif
  230. #ifdef USE_TERMIOS
  231.         tcgetattr(fileno(stdin), &zap);
  232.       zap.c_cc[VMIN] = 0;     /* can't work with old */
  233.       zap.c_cc[VTIME] = 0; /* FreeBSD versions    */
  234.       zap.c_lflag &= ~(ICANON|ECHO|ECHONL);
  235.       tcsetattr(fileno(stdin), TCSADRAIN, &zap);
  236. #endif
  237.       is_fg = TRUE;
  238.       }
  239.    else
  240.       is_fg = FALSE;
  241.    }
  242.  
  243. /* nonblocking_io():
  244.  * try to setup the keyboard to non blocking io
  245.  */
  246. LOCAL void nonblocking_io()
  247.    {
  248.  
  249.  
  250. #if 0 /* BROKEN */
  251.    /* try to renice our own process to get more cpu time */
  252.    if (nice(-15) == -1)
  253.       nice(0);
  254. #endif
  255.  
  256.  
  257.    if (!psanity)
  258.       {
  259.       psanity = &sanity;
  260. #ifdef USE_SGTTY
  261.       ioctl(fileno(stdin), TIOCGETP, psanity);
  262. #endif
  263. #ifdef USE_TERMIOS
  264.       tcgetattr(fileno(stdin), psanity);
  265. #endif
  266.       }
  267.    switch_mode();
  268.    at_end(if_fg_sane_tty);
  269.    }
  270.  
  271.  
  272. /* sane_tty():
  273.  * restores everything to a sane state before returning to shell */
  274. LOCAL void sane_tty()
  275.    {
  276. #ifdef USE_SGTTY
  277.       ioctl(fileno(stdin), TIOCSETP, psanity);
  278. #endif
  279. #ifdef USE_TERMIOS
  280.       tcsetattr(fileno(stdin), TCSADRAIN, psanity);
  281. #endif
  282.    }
  283.  
  284. LOCAL int may_getchar()
  285.    {
  286.    char buffer;
  287.  
  288.    INIT_ONCE;
  289.  
  290.    if (run_in_fg() && !is_fg)
  291.       switch_mode();
  292.    if (run_in_fg() && read(fileno(stdin), &buffer, 1))
  293.       return buffer;
  294.    return EOF;
  295.    }
  296.  
  297. LOCAL struct tag result[2];
  298.  
  299. struct tag *get_ui()
  300.    {
  301.     int c;
  302.  
  303.    result[0].type = TAG_END;
  304.    result[1].type = TAG_END;
  305.    count_pattern++;
  306.    count_song++;
  307.    switch(c = may_getchar())
  308.       {
  309.    case 'n':
  310.       result[0].type = UI_NEXT_SONG;
  311.       break;
  312.    case 'p':
  313.       if (count_song > SMALL_DELAY)
  314.          result[0].type = UI_RESTART;
  315.       else
  316.          result[0].type = UI_PREVIOUS_SONG;
  317.       count_song = 0;
  318.       break;
  319.    case 'x':
  320.    case 'e':
  321.    case 'q':
  322.       result[0].type = UI_QUIT;
  323.       break;
  324.    case 's':
  325.       result[0].type = UI_SET_BPM;
  326.       result[0].data.scalar = 50;
  327.       break;
  328.    case 'S':
  329.       result[0].type = UI_SET_BPM;
  330.       result[0].data.scalar = 60;
  331.       break;
  332.    case '>':
  333.       result[0].type = UI_JUMP_TO_PATTERN;
  334.       result[0].data.scalar = current_pattern + 1;
  335.       break;
  336.    case '<':
  337.       result[0].type = UI_JUMP_TO_PATTERN;
  338.       result[0].data.scalar = current_pattern;
  339.       if (count_pattern < SMALL_DELAY)
  340.          result[0].data.scalar--;
  341.       break;
  342.    case '?':
  343.         set_pref_scalar(PREF_SHOW, !get_pref_scalar(PREF_SHOW));
  344.         if (get_pref_scalar(PREF_SHOW))
  345.             putchar('\n');
  346.       break;
  347.    default:
  348.         audio_ui(c);
  349.       break;
  350.       }
  351.    return result;
  352.    }
  353.       
  354.          
  355. #endif
  356.  
  357.  
  358. void notice(s)
  359. char *s;
  360.    {
  361.    fprintf(stderr, "%s\n", s);
  362.    }
  363.  
  364. void status(s)
  365. char *s;
  366.    {
  367.    if (run_in_fg())
  368.       {
  369.         if (s)
  370.          {
  371.          puts(s);
  372.          }
  373.       else
  374.          putchar('\n');
  375.       }
  376.    }
  377.  
  378. LOCAL char title[25];
  379. void song_title(s)
  380. char *s;
  381.    {
  382.     strncpy(title, s, 25);
  383.    count_song = 0;
  384.    }
  385.  
  386.  
  387. LOCAL char scroll_buffer[200];
  388.  
  389. GENERIC begin_info(title)
  390. char *title;
  391.    {
  392.    if (run_in_fg())
  393.       return scroll_buffer;
  394.    else
  395.       return 0;
  396.    }
  397.  
  398. void infos(handle, s)
  399. GENERIC handle;
  400. char *s;
  401.    {
  402.    if (handle)
  403.       printf(s);
  404.    }
  405.  
  406. void info(handle, line)
  407. GENERIC handle;
  408. char *line;
  409.    {
  410.    if (handle)
  411.       puts(line);
  412.    }
  413.  
  414. void end_info(handle)
  415. GENERIC handle;
  416.    {
  417.    if (handle)
  418.       fflush(stdout);
  419.    }
  420.  
  421. LOCAL char *last_result = 0;
  422.  
  423. LOCAL int ntracks;
  424.  
  425. void set_number_tracks(n)
  426. int n;
  427.     {
  428.     ntracks = n;
  429.     }
  430.  
  431. LOCAL void clear_scroll(temp)
  432. char *temp;
  433.     {
  434.     int i;
  435.  
  436.     if (get_pref_scalar(PREF_COLOR))
  437.         {
  438.         for (i = 0; i * 2 < ntracks; i++)
  439.             {
  440.             strcpy(temp, "                    ");
  441.             temp = write_color(temp + 20, 0);
  442.             *temp++ = '|';
  443.             }
  444.         *temp++ = '|';
  445.         for (i = 0; i * 2 < ntracks; i++)
  446.             {
  447.             strcpy(temp, "                    ");
  448.             temp = write_color(temp + 20, 0);
  449.             *temp++ = '|';
  450.             }
  451.         }
  452.     else
  453.         {
  454.         for (i = 0; i * 2 < ntracks; i++)
  455.             {
  456.             strcpy(temp, "             |");
  457.             temp += 14;
  458.             }
  459.         *temp++ = '|';
  460.         for (i = 0; i * 2 < ntracks; i++)
  461.             {
  462.             strcpy(temp, "             |");
  463.             temp += 14;
  464.             }
  465.         }
  466.     *temp = '\0';
  467.     }
  468.  
  469. char *new_scroll()
  470.    {
  471.     last_result = 0;
  472.  
  473.    if (run_in_fg())
  474.       last_result = malloc(200);
  475.     if (last_result)
  476.         clear_scroll(last_result);
  477.    return last_result;
  478.    }
  479.    
  480. LOCAL void do_scroll(char *line)
  481.     {
  482.    if (run_in_fg())
  483.         {
  484.       puts(line);    
  485.         fflush(stdout);
  486.         free(line);
  487.         }
  488.    }
  489.  
  490. void scroll()
  491.    {
  492.     if (last_result)
  493.         sync_audio(do_scroll, last_result);
  494.     }
  495.  
  496. LOCAL void do_display_pattern(int *thingy)
  497.     {
  498.     int current, total, real;
  499.     current = thingy[0];
  500.     total = thingy[1];
  501.     real = thingy[2];
  502.     free(thingy);
  503.  
  504.    if (run_in_fg())
  505.         {
  506.           if (get_pref_scalar(PREF_XTERM))
  507.               {
  508.             if (get_pref_scalar(PREF_SHOW))
  509.                 {
  510.                 int i;
  511.                 for (i = 0; i < ntracks; i++)
  512.                     printf("--------------");
  513.                 printf("\033]2;tracker %s %3d/%3d[%3d] %s\007\n", VERSION,
  514.                     current, total, real, title);
  515.                 }
  516.             else
  517.                 {
  518.                 printf("\033]2;tracker %s %3d/%3d %s\007", VERSION, 
  519.                     current, total, title);
  520.                 fflush(stdout);
  521.                 }
  522.               }
  523.         else
  524.               {
  525.             if (get_pref_scalar(PREF_SHOW))
  526.                 printf("\n%3d/%3d[%3d] %s\n", current, total, real, title);
  527.             else
  528.                 printf("%3d/%3d\b\b\b\b\b\b\b", current, total);
  529.             fflush(stdout); 
  530.            }
  531.       }
  532.    current_pattern = current;
  533.    count_pattern = 0;
  534.    }
  535.  
  536. void display_pattern(current, total, real)
  537. int current, total, real;
  538.    {
  539.     int *thingy;
  540.  
  541.     thingy = malloc(sizeof(int)*3);
  542.     thingy[0] = current;
  543.     thingy[1] = total;
  544.     thingy[2] = real;
  545.     sync_audio(do_display_pattern, thingy);
  546.     }
  547.  
  548. int checkbrk()
  549.    {
  550.    return FALSE;
  551.    }
  552.